package com.jiufengxinxi.ts.device.equipment.rfid;

import com.jiufengxinxi.ts.common.utils.thread.BaseThreadRunnable;
import com.jiufengxinxi.ts.common.utils.thread.ExecutorServiceUtils;
import com.jiufengxinxi.ts.device.callback.IDeviceStateCallback;
import com.jiufengxinxi.ts.device.equipment.SerialTransportRXTX;
import com.jiufengxinxi.ts.device.interfaces.IReadDevice;
import com.thingmagic.*;
import com.thingmagic.SerialReader.ReaderStats;
import com.thingmagic.SerialReader.StatusReport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.*;

@Component
public class RfidOperateOld implements IReadDevice,ReadExceptionListener,StatusListener,StatsListener,ReadListener{

	private Logger logger= LoggerFactory.getLogger(this.getClass());

	/*@Autowired
	private ConfigService configService;*/

	private String readerURI = "";
	private boolean trace=false;
	private int[] antennaList;

	private String[] antennaGroup;

	private IReaderStopListen readerStopListe=new ReaderStopListen();


	private TransportListener currentListener;

	private Reader r = null;

	private int state = 0;// 0=未初始,1=已经初始，2=监听读卡中,3=读卡中,4=写卡中

	private int opstate = 0;//当前执行的操作状态

	private int readType = 0;// 0=EPC,1=TID

	private int power = 3150;

	private int setplan_times = 0;//

	private boolean directReading = true;// 直读模式

	private String model;

	private Map<String,Object> workMap=new HashMap<String,Object>();

	private String strDateFormat = "M/d/yyyy h:m:s a";

	private SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);

	private IReadListener readListener;

	private boolean exception = false;

	private IDeviceStateCallback deviceCallback;

	private Thread threadThrad = null;

	public RfidOperateOld() {
		super();
		try {
			Reader.setSerialTransport("tmr", new SerialTransportRXTX.Factory());
			Reader.setSerialTransport("eapi", new SerialTransportRXTX.Factory());
			/*if(configService==null) {
				configService = ServicesFactory.getBean(ConfigService.class);
			}
			init(configService.getSystemConfig().getReaderAddress(), configService.getSystemConfig().getAntennas(),configService.getSystemConfig().getReaderPower());*/
			initThread();
		} catch (ReaderException e) {
			e.printStackTrace();
		}
		
	}

	public RfidOperateOld(String readerURI, boolean trace, String[] antennaGroup, int readerPower) {
		super();
		try {
			Reader.setSerialTransport("tmr", new SerialTransportRXTX.Factory());
			Reader.setSerialTransport("eapi", new SerialTransportRXTX.Factory());
			init(readerURI,antennaGroup,readerPower);
			initThread();
		} catch (ReaderException e) {
			e.printStackTrace();
		}
	}


	public synchronized void rfidOperate(int type) throws ReaderException {
		this.opstate = type;
		synchronized (readerURI){
			switch (type){
				case 0:{
					logger.info("+++++++++++++++++++++++++++++++++++开始销毁读写器连接+++++++++++++++++++++++++++++++++++");
					if(r!=null){
						if(state == 0) {
							return;
						}
						
						if(state == 2) {
							r.stopReading();
						}
						//stopListen();
						r.removeStatusListener(this);

						r.removeReadExceptionListener(this);
						state=0;

						if(readerStopListe!=null){
							readerStopListe.stop(workMap);
						}
						workMap.clear();
						r.destroy();

					}
					logger.info("reader destored");
				}break;
				case 1:{
					logger.info("+++++++++++++++++++++++++++++++++++开始初始化读写器连接+++++++++++++++++++++++++++++++++++");
					if(state==1) {
						return;
					}
					r = Reader.create(readerURI);
					r.connect();
					if (trace) {
						setTrace(r, new String[] { "on" });
					}else{
						setTrace(r, new String[] { "off" });
					}
					r.addStatusListener(this);

					//exceptionListener = new TagReadExceptionReceiver();
					r.addReadExceptionListener(this);
					// Create and add tag listener



					r.addStatsListener(this);
					writePower(power);

                    /**
                     * 不执行这些，读到的卡会被截短
                     */
					if (Reader.Region.UNSPEC == (Reader.Region) r.paramGet("/reader/region/id")) {
						Reader.Region[] supportedRegions = (Reader.Region[]) r.paramGet(TMConstants.TMR_PARAM_REGION_SUPPORTEDREGIONS);
						if (supportedRegions.length < 1) {
							throw new ReaderException("Reader doesn't support any regions");
						} else {
							r.paramSet("/reader/region/id", supportedRegions[0]);
						}
					}

					model = r.paramGet("/reader/version/model").toString();
					
					if ((model.equalsIgnoreCase("M6e Micro") || model.equalsIgnoreCase("M6e Nano")) && antennaList == null)
			        {
			            System.out.println("Module doesn't has antenna detection support, please provide antenna list");
			            r.destroy();
			            //
			        }
					state=1;
					exception = false;
					logger.info("reader inited");
				}break;
				case 2:{
					try {


						if(directReading){
							setReadPlan();
							TagReadData[] tagReads = r.read(200);
							proTag(tagReads);
						}else {
							logger.info("+++++++++++++++++++++++++++++++++++开始打开读写器监听+++++++++++++++++++++++++++++++++++");
							if (state == 2) {
								return;
							}
							state = 2;
							setReadPlan();
							r.addReadListener(RfidOperateOld.this);
							r.startReading();
							logger.info("+++++++++++++++++++++++++++++++++++成功打开读写器监听+++++++++++++++++++++++++++++++++++");
						}


					}catch (ReaderException ex){
						logger.error("打开读卡监听异常");
						tagReadException(r,ex);
					}

				}break;
				case 3:{

				}break;
				case 4:{

				}break;
				case -1:{
					logger.info("+++++++++++++++++++++++++++++++++++开始关闭读写器监听+++++++++++++++++++++++++++++++++++");

					if(directReading){
						state = 1;
					}else{
						if (state == 1) {
							return;
						}
						r.removeReadListener(RfidOperateOld.this);
						r.stopReading();
						state = 1;
					}
					if (readerStopListe != null) {
						readerStopListe.stop(workMap);
					}
					workMap.clear();
					logger.info("+++++++++++++++++++++++++++++++++++成功关闭读写器监听+++++++++++++++++++++++++++++++++++");
				}break;
			}
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public void proTag(TagReadData[] tagReads){
//		if(tagReads==null){
//			System.out.println("没有读到卡");
//		}else{
//			System.out.println("读到"+tagReads.length+"张卡");
//		}

		for(TagReadData tag:tagReads){
			//System.out.println("读到"+tag.toString());
			tagRead(r, tag);
		}
	}

	public void initThread(){

		if(threadThrad==null){
			threadThrad = new Thread(new Runnable() {
				@Override
				public void run() {
					while (true){
						try{
							if(directReading&&state==2){
								rfidOperate(2);
							}
							Thread.sleep(30);
						}catch (Exception e){
							logger.error("打开读卡执行异常",e);
						}
					}
				}
			});
			threadThrad.start();
		}
	}
	
	public void init(String readerURI, String[] antennaGroup,int readerPower) throws ReaderException {

		this.readerURI = readerURI;
		this.power=readerPower;
		this.antennaGroup=antennaGroup;
		if(antennaGroup==null) {
			return ;
		}
		
		List<Integer> antennas=new ArrayList<Integer>();
		for(String as:antennaGroup){
			String[] at=as.split(",");
			for(String a:at){
				antennas.add(Integer.parseInt(a));
			}
		}
		
		this.antennaList=new int[antennas.size()];
		for(int i=0;i<antennaList.length;i++){
			antennaList[i]=antennas.get(i);
		}
		rfidOperate(1);
	}
	
	
	public void init() throws ReaderException{
		if(state!=0){
			return;
		}
		logger.info("开始初始化写器连接");
		rfidOperate(1);
		//System.out.println("读写器串口:"+readerURI);

	}
	
	public void destroy(){
		if(state==0){
			return;
		}
		try {
			rfidOperate(0);
		} catch (ReaderException e) {
			logger.error(e.getLocalizedMessage());
		}
	}

	public  void listen() throws ReaderException{
		if(state==0){
			init();
		}

		if(state!=1){
			return;
		}

		if(directReading){
			state = 2;
		}else{
			rfidOperate(2);
		}
		//
		logger.info("reader reading started");
	}

	public void stopListen() throws ReaderException {
		if(r==null||state!=2){
			return;
		}

		if(directReading){
			state = 1;
		}else{
			rfidOperate(-1);
		}
		logger.info("reader reading stoped");

		//destroy();
	}
	
	
	public String write(String tag,String targetTag,int antenna){
		if(state!=1){
			return "当前状态不可写卡";
		}
		try {
			if (antennaList != null){
				r.paramSet("/reader/tagop/antenna", antenna);
			}
			
			state=4;
			TagFilter target = parseEPC(targetTag);
			
			Gen2.TagData epc = new Gen2.TagData(tag);
			Gen2.WriteTag tagop = new Gen2.WriteTag(epc);
			r.executeTagOp(tagop, target);

		} catch (ReaderException e) {
			// TODO Auto-generated catch block
			logger.error("write error!!"+e.getMessage(),e);
			return e.getMessage();
		}catch(Exception ex){
			ex.printStackTrace();
			return "写卡异常";
		}finally {
			state=1;
		}
		logger.info("reader carnum writed "+targetTag);
		return null;
	}
	
	
	public List<String> read() throws Exception {
		TagReadData[] tagReads = null;
		List<String> tags=null;
		if(state!=1){
			return null;
		}
		state=3;
		
		setReadPlan();
        
     // Read tags
        tagReads = r.read(100);
        // Print tag reads
        
        tags=new ArrayList<String>();
        
        for (TagReadData tr : tagReads)
        {
        	tags.add(tr.toString());
            System.out.println(tr.getTag().epcString());
        }
        
        state=1;


		return tags;
	}
	
	public boolean writePower(int readPower) {
		try {
			logger.info("old power "+r.paramGet(TMConstants.TMR_PARAM_RADIO_READPOWER));
			r.paramSet("/reader/radio/enablePowerSave", true);
			r.paramSet(TMConstants.TMR_PARAM_RADIO_READPOWER, readPower);
			logger.info("new power "+r.paramGet(TMConstants.TMR_PARAM_RADIO_READPOWER));
			return true;
		} catch (ReaderException e) {
			e.printStackTrace();
			return false;
		}
	}
	
	private void setReadPlan() throws ReaderException {
		TagOp op=null;
		switch (readType) {
			case 1:
				byte length;
				if ("M6e".equals(model) || "M6e Micro".equals(model) || "M6e PRC".equals(model) || "Mercury6".equals(model) || "Astra-EX".equals(model))
	            {
	                length = 0;
	            }
	            else
	            {
	                length = 2;
	            }
				op=new Gen2.ReadData(Gen2.Bank.TID, 0, length);
				break;
	
			default:
				break;
		}
		
		SimpleReadPlan plan = new SimpleReadPlan(antennaList, TagProtocol.GEN2, null, op, 1000);
		r.paramSet(TMConstants.TMR_PARAM_READ_PLAN, plan);
		setplan_times=0;
	}
	
	
	static TagFilter parseEPC(String arg)
	  {

	    if (arg.equalsIgnoreCase("any"))
	      return null;
	    else if (arg.substring(0,4).equalsIgnoreCase("epc:"))
	      return new TagData(arg.substring(4));
	    else if (arg.substring(0,5).equalsIgnoreCase("gen2:"))
	      return new Gen2.TagData(arg.substring(5));
	    else
	      return new TagData(arg);
	  }

	public void setTrace(Reader r, String args[]) {
		if (args[0].toLowerCase().equals("on"))
	    {
	        r.addTransportListener(Reader.simpleTransportListener);
	        currentListener = Reader.simpleTransportListener;
	    }
	    else if (currentListener != null)
	    {
	        r.removeTransportListener(Reader.simpleTransportListener);
	    }
	}
	
	

	public Map<String, Object> getWorkMap() {
		return workMap;
	}

	public void setWorkMap(Map<String, Object> workMap) {
		this.workMap = workMap;
	}


	public String getReaderURI() {
		return readerURI;
	}

	public void setReaderURI(String readerURI) {
		this.readerURI = readerURI;
	}

	public boolean isTrace() {
		return trace;
	}

	public void setTrace(boolean trace) {
		this.trace = trace;
	}

	public int[] getAntennaList() {
		return antennaList;
	}

	public void setAntennaList(int[] antennaList) {
		this.antennaList = antennaList;
	}

	public Reader getR() {
		return r;
	}

	public void setR(Reader r) {
		this.r = r;
	}


	public int getState() {
		return state;
	}

	public void setState(int state) {
		this.state = state;
	}

	public TransportListener getCurrentListener() {
		return currentListener;
	}

	public void setCurrentListener(TransportListener currentListener) {
		this.currentListener = currentListener;
	}


	public String[] getAntennaGroup() {
		return antennaGroup;
	}

	public void setAntennaGroup(String[] antennaGroup) {
		this.antennaGroup = antennaGroup;
	}

	

	public IReaderStopListen getReaderStopListe() {
		return readerStopListe;
	}

	public void setReaderStopListe(IReaderStopListen readerStopListe) {
		this.readerStopListe = readerStopListe;
	}

	public int getReadType() {
		return readType;
	}

	public void setReadType(int readType) {
		this.readType = readType;
	}

	@Override
	public void tagReadException(Reader arg0, ReaderException re) {

		if(exception){
			return;
		}

		ExecutorServiceUtils.execute(new BaseThreadRunnable() {
			@Override
			public boolean isUseLock() {
				return false;
			}

			@Override
			public String getName() {
				return null;
			}

			@Override
			public void running() {

				exception = true;

				String format = sdf.format(Calendar.getInstance().getTime());
				logger.error("=========读写器操作异常: " + re.getMessage() + " 时间 :" + format, re);

				try {
					r.reboot();
				} catch (ReaderException e) {
					e.printStackTrace();
				}

				try {
					//destroy();
					SerialTransportRXTX transportRXTX=SerialTransportRXTX.getInstence(readerURI.replace("tmr://",""));
					transportRXTX.shutdown();
					if(RfidOperateOld.this.opstate==0||RfidOperateOld.this.opstate==-1){
						return;
					}
					int state = RfidOperateOld.this.opstate;
					RfidOperateOld.this.opstate = 0;
					rfidOperate(state);
				} catch (ReaderException e) {
					e.printStackTrace();
				}
			}
		});
		crash(r, re);
	}

	@Override
	public void statusMessage(Reader arg0, StatusReport[] arg1) {
		for(StatusReport status:arg1){
			logger.info("==========读写器当前状态："+status.toString());
		}
	}

	@Override
	public void statsRead(ReaderStats arg0) {
		logger.info("==========读写器> temperature:"+arg0.temperature+"    frequency:"+arg0.frequency+"     antenna:"+arg0.antenna+"    protocol:"+arg0.protocol.name());
		
	}

	@Override
	public String status() {
		return String.valueOf(getState());
	}

	@Override
	public boolean check() {
		return false;
	}

	@Override
	public void startup() {
		try {
			init();
		} catch (ReaderException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public String getDeviceName() {
		return "m6e";
	}

	@Override
	public void setDeviceCallback(IDeviceStateCallback deviceCallback) {
		this.deviceCallback = deviceCallback;
	}
	
	public void crash(Reader r,Exception e) {
		if(this.deviceCallback!=null) {
			this.deviceCallback.crash(r, e);
		}
	}

	public IReadListener getReadListener() {
		return readListener;
	}

	public void setReadListener(IReadListener readListener) {
		this.readListener = readListener;
	}

	@Override
	public void tagRead(Reader r, TagReadData tr) {
		StringBuffer cardNum=new StringBuffer();
		
		if(getReadType()==1) {
			//cardNum="";
			for (byte b : tr.getData())
            {
				String bt=Integer.toHexString(b & 0xFF);
				if(bt.length()==1) {
					bt="0"+bt;
				}
				//cardNum+=bt;
				cardNum.append(bt);
                /*System.out.printf("%02x", b);
                System.out.printf("\n");*/
            }
		}else {
			cardNum.append(tr.getTag().epcString());
			//cardNum=tr.getTag().epcString();
		}
		
		//System.out.println("卡号："+cardNum);
		
		if(this.readListener!=null) {
			this.readListener.tag(getReadType()==1?cardNum.toString():"", tr.getTag().epcString(), tr.getAntenna(), tr.getRssi());
		}
		
	}


}
